
/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2022原作者。
 *
 *根据Apache许可证2.0版（“许可证”）许可；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，否则软件
 *根据许可证分发是在“按原样”的基础上分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证
 *许可证下的限制。
 */

package org.springframework.context.event;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Predicate;

import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.context.ApplicationEvent;
import org.springframework.core.annotation.AliasFor;

/**
 * Annotation that marks a method as a listener for application events.
 *
 * <p>If an annotated method supports a single event type, the method may
 * declare a single parameter that reflects the event type to listen to.
 * If an annotated method supports multiple event types, this annotation
 * may refer to one or more supported event types using the {@code classes}
 * attribute. See the {@link #classes} javadoc for further details.
 *
 * <p>Events can be {@link ApplicationEvent} instances as well as arbitrary
 * objects.
 *
 * <p>Processing of {@code @EventListener} annotations is performed via
 * the internal {@link EventListenerMethodProcessor} bean which gets
 * registered automatically when using Java config or manually via the
 * {@code <context:annotation-config/>} or {@code <context:component-scan/>}
 * element when using XML config.
 *
 * <p>Annotated methods may have a non-{@code void} return type. When they
 * do, the result of the method invocation is sent as a new event. If the
 * return type is either an array or a collection, each element is sent
 * as a new individual event.
 *
 * <p>This annotation may be used as a <em>meta-annotation</em> to create custom
 * <em>composed annotations</em>.
 *
 * <h3>Exception Handling</h3>
 * <p>While it is possible for an event listener to declare that it
 * throws arbitrary exception types, any checked exceptions thrown
 * from an event listener will be wrapped in an
 * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
 * since the event publisher can only handle runtime exceptions.
 *
 * <h3>Asynchronous Listeners</h3>
 * <p>If you want a particular listener to process events asynchronously, you
 * can use Spring's {@link org.springframework.scheduling.annotation.Async @Async}
 * support, but be aware of the following limitations when using asynchronous events.
 *
 * <ul>
 * <li>If an asynchronous event listener throws an exception, it is not propagated
 * to the caller. See {@link org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
 * AsyncUncaughtExceptionHandler} for more details.</li>
 * <li>Asynchronous event listener methods cannot publish a subsequent event by returning a
 * value. If you need to publish another event as the result of the processing, inject an
 * {@link org.springframework.context.ApplicationEventPublisher ApplicationEventPublisher}
 * to publish the event manually.</li>
 * </ul>
 *
 * <h3>Ordering Listeners</h3>
 * <p>It is also possible to define the order in which listeners for a
 * certain event are to be invoked. To do so, add Spring's common
 * {@link org.springframework.core.annotation.Order @Order} annotation
 * alongside this event listener annotation.
 *
 * @author Stephane Nicoll
 * @author Sam Brannen
 * @since 4.2
 * @see EventListenerMethodProcessor
 * @see org.springframework.transaction.event.TransactionalEventListener
 */
/**
 *将方法标记为应用程序事件的侦听器的注释。
 *
 *<p>如果带注释的方法支持单个事件类型，则该方法可能
 *声明一个反映要侦听的事件类型的参数。
 *如果带注释的方法支持多个事件类型，则此注释
 *可以使用｛@code classes｝引用一个或多个受支持的事件类型
 *属性。有关更多详细信息，请参阅{@link#classes}javadoc。
 *
 *＜p＞事件可以是｛@link ApplicationEvent｝实例，也可以是任意实例
 *对象。
 *
 *＜p＞｛@code@EventListener｝注释的处理通过
 *内部｛@link EventListenerMethodProcessor｝bean
 *使用Java配置时自动注册，或通过
 *｛@code＜context:annotation config/＞｝或｛@ccode＜context:component scan/＞｝
 *元素。
 *
 *＜p＞带注释的方法可能具有非｛@code void｝的返回类型。当他们
 *这样，方法调用的结果将作为一个新事件发送。如果
 *返回类型是数组或集合，每个元素都被发送
 *作为一个新的个人事件。
 *
 *<p>此注释可以用作<em>元注释</em>以创建自定义
 *<em>组合注释</em>。
 *
 *<h3>异常处理</h3>
 *＜p＞虽然事件侦听器可以声明
 *抛出任意异常类型，抛出任何已检查的异常
 *来自事件的侦听器将封装在
 *｛@link java.lang.reflectUndeclaredThrowableException未声明的ThrowableException｝
 *因为事件发布者只能处理运行时异常。
 *
 *<h3>异步侦听器</h3>
 *<p>如果您希望特定的侦听器异步处理事件，那么
 *可以使用Spring的｛@link org.springframework.scheduling.annotation.Async@Async｝
 *支持，但在使用异步事件时要注意以下限制。
 *
 *＜ul＞
 *＜li＞如果异步事件侦听器抛出异常，则不会传播
 *呼叫方。请参阅｛@link org.springframework.aop.interceptor.AsyncUncaughtException Handler
 *有关详细信息，请参阅AsyncUnaughtException Handler｝</li>
 *＜li＞异步事件侦听器方法无法通过返回
 *价值。如果您需要发布另一个事件作为处理的结果，请注入
 *｛@link org.springframework.context.ApplicationEventPublisher应用程序事件发布器｝
 *以手动发布事件</li>
 *</ul>
 *
 *<h3>订购听众</h3>
 *＜p＞还可以定义
 *要调用某些事件。为此，添加Spring的公共
 *｛@link org.springframework.core.annotation.Order@Order｝注释
 *以及此事件侦听器注释。
 *
 *@作者Stephane Nicoll
 *@作者Sam Brannen
 *@自4.2起
 *@参见EventListenerMethodProcessor
 *@参见org.springframework.transaction.event.TransactionalEventListener
 */
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface EventListener {

	/**
	 * Alias for {@link #classes}.
	 */
	/**
	 *｛@link#classes｝的别名。
	 */
	@AliasFor("classes")
	Class<?>[] value() default {};

	/**
	 * The event classes that this listener handles.
	 * <p>If this attribute is specified with a single value, the
	 * annotated method may optionally accept a single parameter.
	 * However, if this attribute is specified with multiple values,
	 * the annotated method must <em>not</em> declare any parameters.
	 */
	/**
	 *此侦听器处理的事件类。
	 *<p>如果使用单个值指定此属性，则
	 *带注释的方法可以选择性地接受单个参数。
	 *但是如果用多个值指定该属性，
	 *带注释的方法必须<em>而不是</em>声明任何参数。
	 */
	@AliasFor("value")
	Class<?>[] classes() default {};

	/**
	 * Spring Expression Language (SpEL) expression used for making the event
	 * handling conditional.
	 * <p>The event will be handled if the expression evaluates to boolean
	 * {@code true} or one of the following strings: {@code "true"}, {@code "on"},
	 * {@code "yes"}, or {@code "1"}.
	 * <p>The default expression is {@code ""}, meaning the event is always handled.
	 * <p>The SpEL expression will be evaluated against a dedicated context that
	 * provides the following metadata:
	 * <ul>
	 * <li>{@code #root.event} or {@code event} for references to the
	 * {@link ApplicationEvent}</li>
	 * <li>{@code #root.args} or {@code args} for references to the method
	 * arguments array</li>
	 * <li>Method arguments can be accessed by index. For example, the first
	 * argument can be accessed via {@code #root.args[0]}, {@code args[0]},
	 * {@code #a0}, or {@code #p0}.</li>
	 * <li>Method arguments can be accessed by name (with a preceding hash tag)
	 * if parameter names are available in the compiled byte code.</li>
	 * </ul>
	 */
	/**
	 *用于生成事件的Spring表达式语言（SpEL）表达式
	 *处理有条件的。
	 *＜p＞如果表达式的计算结果为布尔值，则将处理该事件
	 *｛@code true｝或以下字符串之一：｛@code“true”｝、｛@code“on”｝，
	 *｛@code“yes”｝或｛@ccode“1”｝。
	 *<p>默认表达式为｛@code“”｝，表示始终处理事件。
	 *<p>SpEL表达式将根据专用上下文进行评估
	 *提供了以下元数据：
	 *＜ul＞
	 *＜li＞｛@code#root.event｝或｛@code event｝以获取对
	 *｛@link应用程序事件｝</li>
	 *＜li＞｛@code#root.args｝或｛@code args｝用于方法的引用
	 *自变量数组</li>
	 *＜li＞方法参数可以通过索引访问。例如，第一个
	 *参数可以通过{@code#root.args[0]｝、{@code-args[0]}、，
	 *{@code#a0}或{@code#00}</li>
	 *＜li＞方法参数可以按名称访问（带有前面的哈希标记）
	 *如果参数名称在编译的字节码中可用</li>
	 *</ul>
	 */
	String condition() default "";

	/**
	 * An optional identifier for the listener, defaulting to the fully-qualified
	 * signature of the declaring method (e.g. "mypackage.MyClass.myMethod()").
	 * @since 5.3.5
	 * @see SmartApplicationListener#getListenerId()
	 * @see ApplicationEventMulticaster#removeApplicationListeners(Predicate)
	 */
	/**
	 *侦听器的可选标识符，默认为完全限定的
	 *声明方法的签名（例如“mypackage.MyClass.myMyMethod（）”）。
	 *@自5.3.5起
	 *@请参阅SmartApplicationListener#getListenerId（）
	 *@see ApplicationEventMulticast#removeApplicationListeners（谓词）
	 */
	String id() default "";

}
